﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using yq.IBase;
using System.Data;
using yq.IBase.DBHelper;
using System.Reflection;
using yq.IBase.Basis;
using cn.Util;

namespace yq.IBase.Basis
{
    /// <summary>
    /// 数据库访问基础类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public  class BusinessBase<T> where T : ModelBase<T>, new()
    {

        public const string WhereStr = " where ";

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="info"></param>
        /// <param name="cn"></param>
        /// <returns></returns>
        public virtual string Add(T info, DbHelper cn)
        {
            return Add(info, Guid.NewGuid().ToString().Replace("-", ""), cn);
        }

        /// <summary>
        /// 添加(自定义key)
        /// </summary>
        /// <param name="info"></param>
        /// <param name="keyValue"></param>
        /// <param name="cn"></param>
        /// <returns></returns>
        public virtual string Add(T info, dynamic keyValue, DbHelper cn)
        {
            bool isKey = true; ;
            var currentT = new T();

            if (info.GetKeyValue().GetType() == typeof(int))
            {
                isKey = false;
            }
            else
            {
                info.SetKeyValue(keyValue);
            }
            string SQL = currentT.GetInsertColumns(IsKey:isKey);

            var comm = cn.GetSqlStringCommond(SQL);
            currentT.GetDbParameters(comm, info, cn);
            cn.ExecuteNonQuery(comm);

            //缓存操作
            cn.CaCheRefresh.Add<T>();

            return keyValue;
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="info"></param>
        /// <param name="cn"></param>
        /// <returns></returns>
        public virtual int Update(T info, DbHelper cn)
        {
            //判断是否已加载
            if (info.IsLoad == false)
            {
                throw new Exception("未加载数据,不允许更新.");
            }
            var currentT = new T();

            ////重写版本号
            //info.SetVersionNewGuid();
         
            string sql = currentT.GetUpdateColumns();
            var comm = cn.GetSqlStringCommond(sql);
            currentT.GetDbParameters(comm, info, cn);

            //缓存操作
            cn.CaCheRefresh.Add<T>();
           
            return cn.ExecuteNonQuery(comm);
        }


        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cn"></param>
        /// <returns></returns>
        public virtual bool Delete(dynamic id, DbHelper cn)
        {
            var currentT = new T();
            string sql = "Delete From " + currentT.GetTableName() + WhereStr + currentT.GetTableKey() + "=@Id";
            var comm = cn.GetSqlStringCommond(sql.ToString());
            System.Data.DbType type = SQLInParameter.GetDbType(id.GetType());
            cn.AddInParameter(comm, "@Id", type, id);
            int i = cn.ExecuteNonQuery(comm);

            //缓存操作
            cn.CaCheRefresh.Add<T>();

            return i != 0;
        }


        /// <summary>
        /// 传入sql语句分页查询 
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="page"></param>
        /// <param name="cn"></param>
        /// <returns></returns>
        public virtual PageList<T> GetPageList(string sql,string orderby, PageModel page, DbHelper cn)
        {
            return new SelectBase<T>().GetPageList(sql, orderby, page, cn);
        }

        /// <summary>
        /// 查询条件
        /// </summary>
        /// <returns></returns>
        public virtual SelectBase<T> Where(Expression<Func<T, bool>> func)
        {
            SelectBase<T> select = new SelectBase<T>();
            select.Where(func);

            return select;
        }

        /// <summary>
        /// 查询条件 空条件
        /// </summary>
        /// <returns></returns>
        public virtual SelectBase<T> Where()
        {
            return new SelectBase<T>();
        }

        /// <summary>
        /// 查询全部数据
        /// </summary>
        /// <param name="cn"></param>
        /// <returns></returns>
        public virtual IList<T> GetAllList(DbHelper cn)
        {
            return new SelectBase<T>().ToList(cn);
        }

        ///// <summary>
        ///// 加载单条
        ///// </summary>
        ///// <param name="id"></param>
        ///// <returns></returns>
        //public virtual T Load(string id, DbHelper cn)
        //{
        //    return ModelBase<T>.Static.Load(id, cn);
        //}

        /// <summary>
        /// 查询全部数据
        /// </summary>
        /// <param name="list"></param>
        /// <param name="cn"></param>
        /// <returns></returns>
        internal virtual IList<T> GetListById(IList<string> list,DbHelper cn)
        {
            T currentT = new T();
            var comm = cn.GetSqlStringCommond("");
            SQLInParameter parameter = new SQLInParameter(cn, comm, true);
            comm.CommandText = new T().GetSelectKey(list);
            var dt = cn.ExecuteDataTable(comm);

            return currentT.GetIList(dt);
        }


        #region 预加载
        
        /// <summary>
        /// 预先填充对象中的子对象
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <param name="func"></param>
        /// <param name="list"></param>
        /// <param name="cn"></param>
        public virtual void Advance<K>(Func<T, ModelBase<K>> func, IList<T> list, DbHelper cn) where K : ModelBase<K>, new()
        {
            //根据外键对象获取外键id的字段名
            string fullName = ForeignKey<T>.Get(typeof(K).Name);

            if (fullName != null)
            {
                PropertyInfo propertySet = typeof(T).GetProperty(typeof(K).Name);
                PropertyInfo property = typeof(T).GetProperty(fullName);

                //AdvanceVal{ key:外键ID，model：主对象实例  }
                var varlist = list.Select(obj =>
                    {
                        var outmodel= new AdvanceVal<T>() { Key = "null" };
                        //反射取值
                        string val = (string)property.GetValue(obj, null);
                        if (string.IsNullOrEmpty(val) == false)
                        {
                            outmodel= new AdvanceVal<T>() { Key = (string)property.GetValue(obj, null), Model = obj };
                        }
                        return outmodel;
                    }
                ).ToList();
                
                //根据外键ID集合取得外键对象集合
                var k_List = new BusinessBase<K>().GetListById(varlist.Select(obj=>obj.Key).ToArray(), cn);

                foreach (var info in k_List)
                {
                    varlist.ForEach(obj =>
                        {   
                            if(obj.Key == info.GetKeyValue())
                            {
                              //反射写入
                               propertySet.SetValue(obj.Model, info, null);
                            }
                        }
                     );
                }
            }
        }

        /// <summary>
        /// 预加载辅助
        /// </summary>
        /// <typeparam name="L"></typeparam>
        private class AdvanceVal<L> where L : ModelBase<L>, new()
        {
            /// <summary>
            /// 主对象的实例
            /// </summary>
           internal L Model { get; set; }

            /// <summary>
            /// 外键的ID
            /// </summary>
           internal string Key { get; set; }
        }
        
        #endregion
    }

}
